Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solve panic issues #275

Merged
merged 6 commits into from
Sep 7, 2023
Merged

Solve panic issues #275

merged 6 commits into from
Sep 7, 2023

Conversation

alovak
Copy link
Contributor

@alovak alovak commented Sep 7, 2023

Closes #269

With this PR we:

  • introduce Validate() method for MessageSpec and field.Spec - so if you don't want constructor to panic, you can validate your spec before.
  • in StringsByHex if sorted value is not a Hex, we compare them as regular strings (no panic)
  • ignore panic in fuzzer, I hope later we can address it

@codecov-commenter
Copy link

codecov-commenter commented Sep 7, 2023

Codecov Report

Patch coverage: 68.29% and project coverage change: +0.20% 🎉

Comparison is base (8252a73) 73.50% compared to head (c54575a) 73.70%.
Report is 7 commits behind head on master.

❗ Current head c54575a differs from pull request most recent head 828c2f1. Consider uploading reports for the commit 828c2f1 to get more accurate results

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #275      +/-   ##
==========================================
+ Coverage   73.50%   73.70%   +0.20%     
==========================================
  Files          43       43              
  Lines        2291     2282       -9     
==========================================
- Hits         1684     1682       -2     
+ Misses        377      369       -8     
- Partials      230      231       +1     
Files Changed Coverage Δ
prefix/ascii.go 71.42% <ø> (ø)
prefix/bcd.go 69.69% <ø> (ø)
prefix/binary.go 64.00% <ø> (ø)
prefix/ebcdic.go 69.69% <ø> (ø)
prefix/ebcdic1047.go 87.50% <ø> (ø)
prefix/hex.go 72.41% <ø> (ø)
sort/strings.go 55.55% <0.00%> (ø)
test/fuzz-reader/reader.go 55.55% <0.00%> (ø)
message_spec.go 70.00% <25.00%> (-30.00%) ⬇️
message.go 71.94% <33.33%> (+0.64%) ⬆️
... and 3 more

... and 1 file with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@PumpkinSeed
Copy link
Contributor

What do you think about creating a NewMessage version with error return? If someone wants to handle it on that way. (Speaking about my own case mostly)

For exmaple:

func NewMessage(spec *MessageSpec) *Message {
	message, err := newMessage(spec)
	if err != nil {
		panic(err) //nolint // as specs moslty static, we panic on spec validation errors
	}
	return message
}

// NOTE: I don't know what would be a good name for that
// NOTE2: There should be an explanation about backward compatibility
func NewMessageWithError(spec *MessageSpec) (*Message, error) {
	return newMessage(spec)
}

func newMessage(spec *MessageSpec) (*Message, error) {
	// Validate the spec
	if err := spec.Validate(); err != nil {
		return nil, err
	}
	.
	.
	...
}

Let me know what you think about it.

@PumpkinSeed
Copy link
Contributor

Also, it closes #269, not #270. :)

@alovak
Copy link
Contributor Author

alovak commented Sep 7, 2023

When you define spec, it will panic if you have a composite field with invalid spec. So, panic happens before NewMessage.

Panicking in Go is generally reserved for situations where it's inappropriate or impossible for the program to continue. In our case, if the spec is not valid, we can't proceed. I believe using panic is acceptable.

message.go Show resolved Hide resolved
@alovak alovak merged commit b652df4 into master Sep 7, 2023
9 checks passed
@alovak alovak deleted the solve-panic-issues branch September 7, 2023 14:53
@PumpkinSeed
Copy link
Contributor

PumpkinSeed commented Sep 7, 2023

When you define spec, it will panic if you have a composite field with invalid spec. So, panic happens before NewMessage.

Panicking in Go is generally reserved for situations where it's inappropriate or impossible for the program to continue. In our case, if the spec is not valid, we can't proceed. I believe using panic is acceptable.

By default I agree on that usage of panic and I'm not trying to push my point of view, but I would like to share some argument to add an exported function with error return. (Note, I don't want to remove the original behavior, I'm just suggesting a minor extension)

First I would like to highlight the usage of the library. By following the original documentation located in the README, we call the message := NewMessage(spec) with a specification defined as JSON and marshalled into the struct representation. We do that every time when we build a new transaction request and also we do that when an incoming message arrives. We do Unpack and Pack.

  1. In idiomatic Go library users didn't expect that the library itself breaks the codes execution. That supposed to be the job of the programs control flow and the writer of the program should be able to take control when the program break it's execution.
  2. In our use-case we are talking about multiple unreliable TCP connection which handled by multiple concurrent workers and channels for in-memory queues. (Probably it's our own failure to write something in that way) In this case one service handle multiple targets of iso8583 compliant backends. So getting a panic in such an unreliable environment puts extra job on the application, however if the error getting returned we could have handle it easily.
  3. I know that the bad spec is not something what we need to execute anymore, but we have multiple different specs (because multiple payment processors has their own and we have at least 5 different one). That would be nice if in case of one bad specification it wouldn't break the entire application and let the scheduler decide whether it propagate the changes to the cluster based on the error log rate.

Based on these arguments I hope you can reconsider the suggestion above.

@adamdecaf
Copy link
Member

I want to understand what you're asking us to reconsider. Are you asking that methods like NewMessage and SetSpec return error instead of panic?

@PumpkinSeed
Copy link
Contributor

@adamdecaf
I had this comment on this pull request.

@PumpkinSeed
Copy link
Contributor

PumpkinSeed commented Sep 8, 2023

@adamdecaf
Sorry I just answered quickly. By following the previously linked comment, I would like you to reconsider that you add an exported function which implements the same as NewMessage, but it returns with error instead of panic. I'm not the best in naming so I mentioned NewMessageWithError, but obviously it's not the best. Based on the reasons and arguments from above, this makes the user of the library able to decide whether the program can handle a panic in case of any issue or they want to handle it themselves by using this new exported function.

The main issue with the NewMessage that it has a lots of unexported part. So I can't write a function which is not relying on panic.

Also I understand if you don't want to add such a change, but I thought I try it. :)

@adamdecaf
Copy link
Member

I don't think supporting backwards compatibility of panics is something we want to support. Causing a panic is very expensive and dangerous to systems. Callers can still panic if they wish, but our libraries always try to avoid that.

@PumpkinSeed
Copy link
Contributor

I don't think supporting backwards compatibility of panics is something we want to support. Causing a panic is very expensive and dangerous to systems. Callers can still panic if they wish, but our libraries always try to avoid that.

I don't want to pick a side in this question, I just offered a possible solution where the caller of the library can decide between the backward compatible way or using another function with error return.

Otherwise I wrote a wrapper solution to avoid panic for our use-case. So I'm also fine with the current implementation as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

avoid using panic in the code
5 participants